package org.uiot.protocol.codec

import spock.lang.Specification

import java.text.SimpleDateFormat

class CachedRuleSpec extends Specification {

    final static dateFormatter = new SimpleDateFormat("yyMMddHHmmss")

    void "test encode/decode"() {
        given:
        def rule = new CachedRule(testcase.params)
        and:
        def bitSrc = new BitSource(testcase.target)
        and:
        def bytes4Encoding = new ByteArrayOutputStream()
        def bitOps4Encoding = new BitOutputStream(bytes4Encoding)

        when:
        def encodingStart = new Date()
        rule.encode(bitOps4Encoding, testcase.value)
        def encodingTime = new Date().time - encodingStart.time
        bitOps4Encoding.close()

        and:
        def decodingStart = new Date()
        def value4Decoding = rule.decode(bitSrc)
        def decodingTime = new Date().time - decodingStart.time

        then:
        bytes4Encoding.toByteArray() == testcase.target
        encodingTime <= testcase.timelimit.encoding

        and:
        value4Decoding == testcase.value
        decodingTime <= testcase.timelimit.decoding

        where:
        testcase << [
                [value: 1, target: [1.byteValue()] as byte[], timelimit: [decoding: 20, encoding: 20], params: [
                        code               : "test", name: "编解码1字节的数字", endian: CodecTraits.ENDIAN.LITTLE, length: 1,
                        lengthUnit         : CodecTraits.LengthUnit.Byte, type: CodecTraits.Type.Numeric,
                        encodingScript: null, decodingScript: null, placeholder: null]],
                [value: 2, target: [2.byteValue()] as byte[], timelimit: [decoding: 10, encoding: 10], params: [
                        code               : "test", name: "编解码8数位的数字", endian: CodecTraits.ENDIAN.LITTLE, length: 8,
                        lengthUnit         : CodecTraits.LengthUnit.Bit, type: CodecTraits.Type.Numeric,
                        encodingScript: null, decodingScript: null, placeholder: null]],
                [value: 0.1, target: [1.byteValue()] as byte[], timelimit: [decoding: 20, encoding: 40], params: [
                        code               : "test", name: "编解码8数位的数字，附带精度转换", endian: CodecTraits.ENDIAN.LITTLE, length: 8,
                        lengthUnit         : CodecTraits.LengthUnit.Bit, type: CodecTraits.Type.Numeric,
                        encodingScript: "x * 10", decodingScript: "x * 0.1", placeholder: null]],
                [value: "helloWorld", target: "helloWorld".bytes, timelimit: [decoding: 10, encoding: 20], params: [
                        code               : "test", name: "编解码10字节的字符串", endian: CodecTraits.ENDIAN.LITTLE, length: 10,
                        lengthUnit         : CodecTraits.LengthUnit.Byte, type: CodecTraits.Type.StringASCII,
                        encodingScript: null, decodingScript: null, placeholder: null]],
                [value: dateFormatter.parse("190407214650"), target: BytesUtils.convertHexStringToByteArray("130407152E32"), timelimit: [decoding: 45, encoding: 20], params: [
                        code               : "date1", name: "编解码十六进制数格式的日期", endian: CodecTraits.ENDIAN.BIG, length: 6,
                        lengthUnit         : CodecTraits.LengthUnit.Byte, type: CodecTraits.Type.Numeric,
                        encodingScript: "Long.parseLong(String.format('%02x%02x%02x%02x%02x%02x',x.format(\"yy\") as int,x.format('MM') as int,x.format('dd') as int,x.format('HH') as int,x.format('mm') as int,x.format('ss') as int),16)",
                        decodingScript: "new java.text.SimpleDateFormat('yyMMddHHmmss').parse(\"\${String.format('%02d', x >> 40 & 0xff)}\${String.format('%02d', x >> 32 & 0xff)}\${String.format('%02d', x >> 24 & 0xff)}\${String.format('%02d', x >> 16 & 0xff)}\${String.format('%02d', x >> 8 & 0xff)}\${String.format('%02d', x >> 0 & 0xff)}\")",
                        placeholder        : null]],
                [value: dateFormatter.parse("121011163849"), target: BytesUtils.convertCompressedBCD2ByteArray("121011163849"), timelimit: [decoding: 20, encoding: 20], params: [
                        code               : "date2", name: "编解码压缩BCD码格式的日期", endian: CodecTraits.ENDIAN.LITTLE, length: 6,
                        lengthUnit         : CodecTraits.LengthUnit.Byte, type: CodecTraits.Type.StringCompressedBCD,
                        encodingScript: "x.format('yyMMddHHmmss')",
                        decodingScript: "new java.text.SimpleDateFormat('yyMMddHHmmss').parse(x)",
                        placeholder        : null]]
        ]
    }
}
